﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.IO.Ports;

namespace ResistorMoudel
{


    [Serializable]
    internal class NewUDPSetting:IPort
    {
        public string local_ip;
        public int local_port;
        public string romote_ip;
        public int romote_port;
        public string port
        {
            get
            {
                return local_port.ToString();
            }
            set
            {
                local_port = int.Parse(value);
            }
        }
    }
    public partial class NewUDP : UserControl, ICommunication
    {
        enum Mode
        {
            Listening,
            Stopping
        }
        NewUDPSetting set = new NewUDPSetting();
        [Obsolete]
        public NewUDP()
        {
            InitializeComponent();
            set = new NewUDPSetting();
            set.local_ip = "0.0.0.0";
            set.romote_ip = "0.0.0.0";
            set.local_port = 0;
            set.romote_port = 0;
            try
            {
                set = (NewUDPSetting)FastData.SaveStatic.ReadBinF(Name);
            }
            catch (Exception exp)
            {
                MessageBox.Show(Name + ": " + exp.ToString());
            }
            _local_ip = set.local_ip;
            _local_port = set.local_port;
            _localIpep = new IPEndPoint(IPAddress.Parse(_local_ip), _local_port); // 本机IP和监听端口号
            _romote_ip = set.romote_ip;
            _romote_port = set.romote_port;
            _romoteIpep = new IPEndPoint(IPAddress.Parse(_romote_ip), _romote_port);

        }
        /// <summary>
        /// 用于UDP发送的网络服务类
        /// </summary>
        IPEndPoint _localIpep;
        IPEndPoint _romoteIpep;
        UdpClient _udpclient;
        /// <summary>
        /// 开关：在监听UDP报文阶段为true，否则为false
        /// </summary>

        /// <summary>
        /// 线程：不断监听UDP报文
        /// </summary>
        /// 
        string _local_ip = "0.0.0.0";
        int _local_port = 60000;
        string _romote_ip = "0.0.0.0";
        int _romote_port = 50000;
        string ContempData = "";
        /// <summary>
        /// 设置本地IP
        /// </summary>
        /// 
        AutoResetEvent resetevent = new AutoResetEvent(false);
        Mode mode = Mode.Stopping;

        IPEndPoint refIpep = new IPEndPoint(0, 0);

        public event Action<string> OnReceiveData;


        Mode MODE
        {
            get
            {
                return mode;
            }
        }



        public string Local_IP
        {
            get
            {
                return _local_ip;
            }
            set
            {
                _local_ip = value;
            }
        }
        /// <summary>
        /// 设置本地端口
        /// </summary>
        public int Local_Port
        {
            get
            {
                return _local_port;
            }
            set
            {
                _local_port = value;



            }
        }

        /// <summary>
        /// 设置远程IP
        /// </summary>
        public string Romote_IP
        {
            get
            {
                return _romote_ip;
            }
            set
            {
                _romote_ip = value;

            }
        }
        /// <summary>
        /// 设置远程端口
        /// </summary>
        public int Romote_Port
        {
            get
            {
                return _romote_port;
            }
            set
            {
                _romote_port = value;

            }
        }

        bool isopen = false;
        public bool IsOpen
        {
            get
            {
                if (_udpclient != null)
                {
                    return isopen;
                }
                else
                {
                    return false;
                }
            }
        }

        public IPort Setting
        {
            get
            {
                return set;
            }
            set
            {
                set = (NewUDPSetting)value;
            }
        }

        protected string allReceivedString;
        public string AllReceivedString
        {
            get
            {
                return allReceivedString;
            }
            set
            {
                allReceivedString = value;
                if (allReceivedString.Length > 99999)
                {
                    allReceivedString.Remove(0, allReceivedString.Length - 99999);
                }
            }
        }

        private bool rtsEnable = false;

        public bool RtsEnable
        {
            get { return rtsEnable; }
            set { rtsEnable = value; }
        }
        private DateTime lastreceiveddatetime;

        public DateTime LastDateTime
        {
            get
            {
                return lastreceiveddatetime;
            }
            set
            {
                lastreceiveddatetime = value;
            }
        }

        [Obsolete]
        public NewUDP(string local_ip, int local_port, string romote_ip, int romote_port)
        {
            InitializeComponent();
            ParentForm.FormClosing += new FormClosingEventHandler(ParentForm_FormClosing);
            _local_ip = local_ip;
            _local_port = local_port;
            _localIpep = new IPEndPoint(IPAddress.Parse(_local_ip), _local_port); // 本机IP和监听端口号
            _udpclient = new UdpClient(_localIpep);

            _romote_ip = romote_ip;
            _romote_port = romote_port;
            _romoteIpep = new IPEndPoint(IPAddress.Parse(_romote_ip), _romote_port);
        }




        public NewUDP(string name)
        {
            InitializeComponent();
            Name = name;

            set.local_ip = "0.0.0.0";
            set.romote_ip = "0.0.0.0";
            set.local_port = 0;
            set.romote_port = 0;
            try
            {
                set = (NewUDPSetting)FastData.SaveStatic.ReadBinF(name);
            }
            catch (Exception exp)
            {
                MessageBox.Show(name + ": " + exp.ToString());
            }

            _local_ip = set.local_ip;
            _local_port = set.local_port;
            _localIpep = new IPEndPoint(IPAddress.Parse(_local_ip), _local_port); // 本机IP和监听端口号
            _udpclient = new UdpClient(_localIpep);
            _romote_ip = set.romote_ip;
            _romote_port = set.romote_port;
            _romoteIpep = new IPEndPoint(IPAddress.Parse(_romote_ip), _romote_port);
        }


        [Obsolete]
        public void SendMessage(string sendContent)
        {
            byte[] data = Encoding.UTF8.GetBytes(sendContent);
            int n = data.Count();
            _udpclient.Send(data, n, _romoteIpep);


        }

        [Obsolete]
        public string ReceiveMessage(ref IPEndPoint _romoteIpep)
        {
            byte[] bytRecv = _udpclient.Receive(ref refIpep);
            string message = Encoding.UTF8.GetString(bytRecv, 0, bytRecv.Length);
            ContempData = message;
            return message;
        }


        /// <summary>
        /// 回调函数
        /// </summary>
        /// <param name="callback"></param>
        [Obsolete]
        public void StartReceivingMessage(Action<string[]> callback)
        {
            Task task = new Task(() =>
            {
                mode = Mode.Listening;
                byte[] data = Encoding.UTF8.GetBytes("  StartReceiving");
                int n = data.Count();
                _udpclient.Send(data, n, _local_ip, _local_port);
                while (mode == Mode.Listening)
                {
                    string message = ReceiveMessage(ref refIpep);
                    ContempData = message;
                    resetevent.Set();
                    callback(new string[] { ContempData });
                }

            }, TaskCreationOptions.LongRunning);
            task.Start();
        }
        [Obsolete]
        public void StartReceivingMessage()
        {
            Task task = new Task(() =>
            {
                mode = Mode.Listening;
                byte[] data = Encoding.UTF8.GetBytes("  StartReceiving");
                int n = data.Count();
                _udpclient.Send(data, n, _local_ip, _local_port);
                while (mode == Mode.Listening)
                {
                    string message = ReceiveMessage(ref refIpep);
                    ContempData = message;
                    resetevent.Set();
                }

            }, TaskCreationOptions.LongRunning);
            task.Start();
        }


        [Obsolete]
        public void StopReceivingMessage()
        {
            mode = Mode.Stopping;
            Thread.Sleep(10);
            byte[] data = Encoding.UTF8.GetBytes("  StopReceiving");
            int n = data.Count();
            _udpclient.Send(data, n, _local_ip, _local_port);
        }



        public static string[] GetLocalIp()
        {
            List<string> IPList = new List<string>();
            ///获取本地的IP地址
            string AddressIP = string.Empty;
            foreach (IPAddress _IPAddress in Dns.GetHostEntry(Dns.GetHostName()).AddressList)
            {
                if (_IPAddress.AddressFamily.ToString() == "InterNetwork")
                {
                    AddressIP = _IPAddress.ToString();
                    IPList.Add(AddressIP);
                }
            }
            return IPList.ToArray();
        }

        private void button3_Click(object sender, EventArgs e)
        {
            set = new NewUDPSetting();
            set.local_ip = textBox1.Text;
            set.local_port = int.Parse(textBox3.Text);
            set.romote_ip = textBox2.Text;
            set.romote_port = int.Parse(textBox4.Text);
            FastData.SaveStatic.SaveBinF(Name, set);

            _local_ip = set.local_ip;
            _local_port = set.local_port;
            _localIpep = new IPEndPoint(IPAddress.Parse(_local_ip), _local_port); // 本机IP和监听端口号
            _romote_ip = set.romote_ip;
            _romote_port = set.romote_port;
            _romoteIpep = new IPEndPoint(IPAddress.Parse(_romote_ip), _romote_port);

        }

        private void NewUDP_Load(object sender, EventArgs e)
        {
            textBox1.Text = _local_ip;
            textBox3.Text = _local_port.ToString();
            textBox2.Text = _romote_ip;
            textBox4.Text = _romote_port.ToString();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //if (mode == Mode.Stopping)
            //{
            //    StartReceivingMessage();
            //}
            //else
            //{
            //    StopReceivingMessage();
            //}
        }

        private void button2_Click(object sender, EventArgs e)
        {
            try
            {
                _local_ip = textBox1.Text;
                _local_port = int.Parse(textBox3.Text);
                _romote_ip = textBox2.Text;
                _romote_port = int.Parse(textBox4.Text);
                _localIpep = new IPEndPoint(IPAddress.Parse(_local_ip), _local_port);
                _romoteIpep = new IPEndPoint(IPAddress.Parse(_romote_ip), _romote_port);
                try
                {
                    _udpclient.Close();
                    _udpclient = null;
                }
                catch { }
            }
            catch
            {
                MessageBox.Show("输入信息有错误！");
            }

        }

        private void NewUDP_ParentChanged(object sender, EventArgs e)
        {
            if (this.ParentForm != null)
            {
                ParentForm.FormClosing += new FormClosingEventHandler(ParentForm_FormClosing);
                ParentForm.AutoSize = true;
                ParentForm.StartPosition = FormStartPosition.CenterScreen;
                ParentForm.Text = Name;
                timer1.Start();
            }
            else
            {
                timer1.Stop();
            }
        }

        private void timer1_Tick(object sender, EventArgs e)
        {

            textBox5.Text = "远程端口：" + ContempData;
            //textBox3.Text = _localIpep.Port.ToString();
            try
            {
                if (_udpclient != null)
                    label11.Text = _udpclient.Client.LocalEndPoint.ToString();
            }
            catch
            {
            }
            label12.Text = _romoteIpep.ToString();
            if (mode == Mode.Listening)
            {
                button1.Text = "停止监听";
            }
            else
            {
                button1.Text = "开始监听";
            }

            if (mode == Mode.Stopping)
            {
                tableLayoutPanel1.Enabled = true;
                button2.Enabled = true;
                button4.Enabled = true;
            }
            else
            {
                tableLayoutPanel1.Enabled = false;
                button2.Enabled = false;
                button4.Enabled = false;
            }

        }

        private void button4_Click(object sender, EventArgs e)
        {

        }

        private void button5_Click(object sender, EventArgs e)
        {
            SendMessage(textBox6.Text);

        }
        private void ParentForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            ((Form)sender).Controls.Clear();
        }

        /// <summary>
        /// UDP发送服务器消息一次默认连接
        /// 两种模式， mode=0 正常发送和接收 ，mode=1开启循环接收模式
        /// </summary>
        public void Open(int mode = 0)
        {
            if (mode == 1)
            {
                ContinueReceiving();


            }
            else
            {
                byte[] data = Encoding.UTF8.GetBytes(_localIpep.ToString());
                int n = data.Length;
                _udpclient.Send(data, n, _romoteIpep);

            }
        }
        Task task = null;
        public void ContinueReceiving()
        {
            string content = "";
            if (_udpclient != null)
            {
                _udpclient.Close();
                _udpclient = null;
            }
            if (task != null)
            {
                //等待线程释放
                while (task.Status == TaskStatus.Running)
                {
                    Thread.Sleep(100);
                }
            }

            _udpclient = new UdpClient(_localIpep);
            //Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff") + "  ================thread is cereated " + Thread.CurrentThread.ManagedThreadId);
            byte[] data = Encoding.UTF8.GetBytes(_localIpep.ToString());
            int n = data.Length;
            _udpclient.Send(data, n, _romoteIpep);

            task = new Task(() =>
            {
                try
                {
                    TimerOutThread timerOutThread = new TimerOutThread(_udpclient);
                    while (true)
                    {
                        timerOutThread.StartListen(5000);
                        byte[] bts = _udpclient.Receive(ref _romoteIpep);
                        isopen = true;
                        timerOutThread.EndListen();
                        int l = bts.Length;
                        if (l == 0)
                        {
                            throw new Exception("");
                        }
                        content = Encoding.UTF8.GetString(bts);
                        ContempData = content;
                        //Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff") + "   收到：" + content);
                        OnReceiveData?.Invoke(content);
                        lastreceiveddatetime = DateTime.Now;
                    }
                }
                catch (Exception exp)
                {
                    try
                    {
                        _udpclient.Close();
                        _udpclient = null;
                    }
                    catch { _udpclient = null; }
                    isopen = false;
                }
            }, TaskCreationOptions.LongRunning);
            task.Start();
            int counttime = 0;
            //阻塞一下，保证已经打开或者超时，返回
            while (!IsOpen)
            {
                counttime++;
                if (counttime > 50)
                {
                    break;
                }
                Thread.Sleep(100);
            }
        }



        public void Close()
        {
            if (_udpclient != null)
            {
                _udpclient.Close();
                _udpclient = null;
            }
        }

        public void Open()
        {
            Open(0);
        }


        public SendBackResult SendBackMessageInstant(string sendContent, int millisecondsTimeOut)
        {
            byte[] data = Encoding.UTF8.GetBytes(_localIpep.ToString());
            int n = data.Length;
            _udpclient.Send(data, n, _romoteIpep);
            byte[] bytRecv = _udpclient.Receive(ref refIpep);
            string message = Encoding.UTF8.GetString(bytRecv, 0, bytRecv.Length);
            ContempData = message;
            return SendBackResult.CreateSuccess(message);
        }
    }


    public class TimerOutThread
    {
        bool isStart = false;
        DateTime lastdatetime = new DateTime();
        int timeoutmilsenconds = 5000;
        public event Action StateChanged;

        public TimerOutThread(UdpClient udpClient, int Circlemilsenconds = 500)
        {
            Task.Factory.StartNew(() =>
            {
                while (true)
                {
                    if (isStart)
                    {
                        if (DateTime.Now - lastdatetime > TimeSpan.FromMilliseconds(timeoutmilsenconds))
                        {
                            udpClient.Close();
                            StateChanged?.Invoke();
                            //Console.WriteLine("线程终止");
                            break;
                        }
                    }
                    Thread.Sleep(Circlemilsenconds);
                }
            }, TaskCreationOptions.LongRunning);
        }

        public void StartListen(int timeoutmilsenconds)
        {
            timeoutmilsenconds = 5000;
            lastdatetime = DateTime.Now;
            isStart = true;
        }

        public void EndListen()
        {
            isStart = false;
        }
    }
}
